using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace Speedball2 {
  public class Bank {
    public string _filename;
    //private int _address;
    private List<Bitmap> _bitmaps;
    private List<Bitmap> _bitmapsBlue;
    private List<Size> _sizes;
    private bool _newFile;
    //private List<int> _addresses;

    public Bank (string filename, byte [] bytes, int width, int height, Palette palette, Palette paletteBlue, Sprite.MasksEnum mask) {
      _filename = filename;
      //_address = address;
      _sizes = new List<Size> ();

      int nb = bytes.Length / ((width * height / 2));
      if (bytes.Length != (nb * width * height / 2))
        throw new Exception ();

      //_addresses = new List<int> ();
      //for (int i = 0; i < nb; i++)
      //  if (address < 0)
      //    _addresses.Add (-1);
      //  else
      //    _addresses.Add (address + i * width * height / 2);
      for (int i = 0; i < nb; i++)
        _sizes.Add (new Size (width, height));
      _bitmaps = new List<Bitmap> (Sprite.CreateBitmaps (bytes, 0, nb, width, height, 4, Sprite.ModesEnum.Interleaved, (width > 8) ? 2 : 1, palette, 0, mask));
      if (paletteBlue != null)
        _bitmapsBlue = new List<Bitmap> (Sprite.CreateBitmaps (bytes, 0, nb, width, height, 4, Sprite.ModesEnum.Interleaved, (width > 8) ? 2 : 1, paletteBlue, 0, mask));
      else {
        _bitmapsBlue = new List<Bitmap> ();
        for (int i = 0; i < nb; i++)
          _bitmapsBlue.Add (null);
      }

      SaveBitmaps (0);

      string fullFilename = Path.Combine (Game.BaseFolder, _filename);
      if (!File.Exists (fullFilename)) {
        bytes.WriteToFile (fullFilename);
        _newFile = true;
      }
      else
        _newFile = false;
      //_bitmaps = new List<Bitmap> ();
      //int nb = bytes.Length / ((width / 2) * height);
      //int offset = 0;
      //for (int i = 0; i < nb; i++) {
      //  _bitmaps = Sprite.CreateBitmaps (bytes, 
      //  offset += width * height / 2;
      //}
    }

    public Bank (string filename, Pc1 pc1) {
      _filename = filename;

      //_addresses = new List<int> ();
      //_addresses.Add (-1);
      //_address = -1;
      _sizes = new List<Size> ();
      _sizes.Add (new Size (pc1._bitmap.Width, pc1._bitmap.Height));
      _bitmaps = new List<Bitmap> ();
      _bitmaps.Add (pc1._bitmap);
      _bitmapsBlue = new List<Bitmap> ();
      _bitmapsBlue.Add (null);

      string fullFilename = Path.Combine (Game.BaseFolder, _filename);
      if (!File.Exists (fullFilename)) {
        pc1._bytes.WriteToFile (fullFilename);
      }
    }

    private void SaveBitmaps (int i) {
      string folder = Path.Combine (Game.BaseFolder, _filename.Replace ('.', '_'));
      if (!Directory.Exists (folder))
        Directory.CreateDirectory (folder);

      for (; i < _bitmaps.Count; i++) {
        Bitmap bitmap = _bitmaps [i];
        string fullFilename = Path.Combine (folder, string.Format ("{0}.png", i.ToString ().PadLeft (3, '0')));
        if (!File.Exists (fullFilename))
          bitmap.Save (fullFilename, ImageFormat.Png);
      }
    }

    public void AddToBank (string filename, byte [] bytes, int width, int height, Palette palette, Palette paletteBlue, Sprite.MasksEnum mask) {
      if (_filename != filename)
        throw new Exception ();

      int from = _bitmaps.Count;
      int nb = bytes.Length / ((width * height / 2));
      if (bytes.Length != (nb * width * height / 2))
        throw new Exception ();

      for (int i = 0; i < nb; i++)
        _sizes.Add (new Size (width, height));
      _bitmaps.AddRange (Sprite.CreateBitmaps (bytes, 0, nb, width, height, 4, Sprite.ModesEnum.Interleaved, (width > 8) ? 2 : 1, palette, 0, mask));
      if (paletteBlue != null)
        _bitmapsBlue.AddRange (Sprite.CreateBitmaps (bytes, 0, nb, width, height, 4, Sprite.ModesEnum.Interleaved, (width > 8) ? 2 : 1, paletteBlue, 0, mask));
      else {
        for (int i = 0; i < nb; i++)
          _bitmapsBlue.Add (null);
      }

      SaveBitmaps (from);

      string fullFilename = Path.Combine (Game.BaseFolder, _filename);
      if (!File.Exists (fullFilename))
        throw new Exception ();
      if (_newFile)
        bytes.AppendToFile (fullFilename);
    }

    public void AddToBank2 (Bank bank) {
      if (_filename != bank._filename)
        throw new Exception ();
      //if (((bank._bitmapsBlue == null) && (bank._bitmapsBlue != null)) ||
      //    ((bank._bitmapsBlue != null) && (bank._bitmapsBlue == null)))
      //  throw new Exception ();
      int nb = _bitmaps.Count;
      //_addresses.AddRange (bank._addresses);
      _sizes.AddRange (bank._sizes);
      _bitmaps.AddRange (bank._bitmaps);
      _bitmapsBlue.AddRange (bank._bitmapsBlue);
      SaveBitmaps (nb);
    }

    public List<Bitmap> GetBitmaps () {
      //if (_bitmapsBlue != null)
      //  throw new Exception ();
      return (_bitmaps);
    }

    public List<Bitmap> GetBitmaps (SideEnum side) {
      //if (_bitmapsBlue == null)
      //  throw new Exception ();
      if (side == SideEnum.Red_0)
        return (_bitmaps);
      else
        return (_bitmapsBlue);
    }

    public Bitmap GetBitmap (int index) {
      //if (_bitmapsBlue != null)
      //  throw new Exception ();
      return (_bitmaps [index]);
    }

    public Bitmap GetBitmap (int index, SideEnum side) {
      //if (_bitmapsBlue == null)
      //  throw new Exception ();
      if (side == SideEnum.Red_0)
        return (_bitmaps [index]);
      else
        return (_bitmapsBlue [index]);
    }

    //public int GetOffset (int i) {
    //  return (_addresses [i]);
    //}

    public int NbBitmaps {
      get {
        return (_bitmaps.Count);
      }
    }

    public Size GetSize (int index) {
      return (_sizes [index]);
    }

    //public Bitmap GetBitmap (int index, SideEnum side) {
    //  return (GetBitmap (index, (int) side));
    //}
  }
}
